"""
异常处理
"""
import traceback
from django.db.models import ProtectedError
from django.http import Http404
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed
from rest_framework.views import set_rollback
from utils.json_response import ErrorResponse
from utils.logger import error_log


class ObjectNotExitException(Exception):
    pass


class ParameterException(Exception):
    # 可以直接使用DRF 异常类进行剖出
    def __init__(self, msg='操作失败！', code=4001, data=None):
        self.detail = msg
        self.code = code
        self.data = data


def CustomExceptionHandler(ex, context):
    """
    统一异常拦截处理
    目的:(1)取消所有的500异常响应,统一响应为标准错误返回
        (2)准确显示错误信息
    :param ex:
    :param context:
    :return:
    """
    msg, code, data = '', 4000, None

    if isinstance(ex, AuthenticationFailed):
        code = 401
        msg = ex.detail
    elif isinstance(ex, Http404):
        code = 404
        msg = '接口地址不正确'
    elif isinstance(ex, ObjectNotExitException):
        code = 406
        msg = '对象不存在'
    elif isinstance(ex, DRFAPIException):
        set_rollback()
        msg = api_error_msg(ex)
    elif isinstance(ex, ProtectedError):
        set_rollback()
        msg = '删除失败:该条数据与其他数据有相关绑定'
    elif isinstance(ex, ParameterException):
        set_rollback()
        msg = api_error_msg(ex)
        code = ex.code
        data = ex.data
    elif isinstance(ex, Exception):
        set_rollback()
        error_log.error(traceback.format_exc())
        msg = str(ex)

    return ErrorResponse(msg=msg, code=code, data=data)


def api_error_msg(ex):
    msg = ex.detail
    if isinstance(msg, dict):
        for k, v in msg.items():
            for i in v:
                msg = '%s:%s' % ('错误' if k == 'non_field_errors' else k, i)
    elif isinstance(msg, list):
        msg = ';'.join(msg)
    return msg
